#include "stdafx.h"
#include "GameApp.h"
#include "GameAppListener.h"

#include "../test/TestAnimation.h"

GameApp* GameApp::m_App = NULL;

GameApp* GameApp::createApp()
{
	if (m_App != NULL)
		return m_App;
	
	m_App = new GameApp();
	return m_App;
}

GameApp::GameApp(void)
{
	m_AppListener	= NULL;
	m_ActiveSession = NULL;
	m_AppTimer		= NULL;

	m_EventService	= NULL;
	m_TaskService	= NULL;
	m_RenderService	= NULL;
	m_InputService	= NULL;

	m_LogManager	= NULL;

	m_ResourcePath	= "..\\data\\";
}

GameApp::~GameApp(void)
{
}

bool GameApp::InitApp()
{
	m_AppTimer = new Ogre::Timer;

	String	pluginPath;

#ifndef OGRE_STATIC_LIB
#ifdef NDEBUG
	pluginPath = m_ResourcePath + "plugins_Release.cfg";
#else if
	pluginPath = m_ResourcePath + "plugins_Debug.cfg";
#endif
#endif

	m_Root = OGRE_NEW Root(pluginPath, m_ResourcePath + "ogre.cfg", m_ResourcePath + "Ogre.log");
	
	setupResource();
	
	if(!m_Root->showConfigDialog())
		return false;
	
	m_Window = m_Root->initialise(true, "IRN_App");

	TextureManager::getSingleton().setDefaultNumMipmaps(5);

	loadResources();

	m_AppListener = new GameAppListener(m_Window);

	InitServices();

	SwitchTo(GameSession::CreateByName("TestAnimation", "")); 
	
	m_Root->addFrameListener(m_AppListener);
	g_App->ChangeActiveSession();

	m_LogManager->LogInit();

	return true;
}


// Resource
//////////////////////////////////////////////////////////////////////////
void GameApp::setupResource()
{
	ConfigFile cf;
	cf.load(m_ResourcePath + "resources.cfg");

	ConfigFile::SectionIterator seci = cf.getSectionIterator();
	String secName, typeName, archName;
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		ConfigFile::SettingsMultiMap *settings = seci.getNext();
		ConfigFile::SettingsMultiMap::iterator itr;
		for (itr = settings->begin(); itr != settings->end(); ++itr)
		{
			typeName = itr->first;
			archName = itr->second;

			ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
		}
	}
}

void GameApp::loadResources()
{
	ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

//////////////////////////////////////////////////////////////////////////

void GameApp::startApp()
{
	if (!InitApp())
		return;

	m_Root->startRendering();
}

void GameApp::endApp()
{
	EndSession();
	FinishServices();
	
	SAFE_DELETE(m_AppListener);
	SAFE_OGRE_DELETE(m_Root);
	SAFE_DELETE(m_AppTimer);
}

void GameApp::InitServices()
{
	AddService(m_EventService,	new EventService());
	AddService(m_TaskService,	new TaskService());
	AddService(m_InputService,	new InputService());
	AddService(m_UIService,		new UIService());
	AddService(m_RenderService, new RenderService());
}

void GameApp::FinishServices()
{
	std::for_each(m_Services.rbegin(), m_Services.rend(), DeleteFunc());
}

void GameApp::ResetServices()
{
	std::for_each(m_Services.begin(), m_Services.end(), std::mem_fun(&Service::Reset));
}

class StartupSession : public GameSession
{
};

REGISTER_GAMESESSION("startup", StartupSession);

void GameApp::SwitchTo(GameSession* session)
{	
	ASSERT(session != NULL);
	m_NextSession = session;
}	

void GameApp::Restart()
{
	if (m_ActiveSession == NULL)
		return;

	const char* name	= m_ActiveSession->GetName();
	const char* arg		= m_ActiveSession->GetArgument();

	GameSession* same = GameSession::CreateByName(name, arg);
	if (same)
		SwitchTo(same);
}

void GameApp::StartSession()
{
	if (m_ActiveSession == NULL)
		return;
	
	m_ActiveSession->StartSession();
	
	if (!m_LogManager)
	{
		m_LogManager = new LogManagement;
		m_LogManager->LogInit();
	}
}

void GameApp::EndSession()
{
	if (m_LogManager)
	{
		m_LogManager->LogShutdown();
		SAFE_DELETE(m_LogManager);
	}

	if (m_ActiveSession == NULL)
		return;

	m_ActiveSession->StopSession();
	m_ActiveSession = NULL;

	ResetServices();
}

void GameApp::ChangeActiveSession()
{
	if (m_NextSession)
	{
		EndSession();

		m_ActiveSession = m_NextSession;
		m_NextSession = NULL;

		StartSession();
	}
}




